"""
音频章节管理服务
"""

import asyncio
import os
from typing import Dict, List, Any, Optional, Tuple
from dataclasses import dataclass
from datetime import datetime, timedelta
from enum import Enum
import json
import tempfile

from ...core.exceptions import BusinessLogicError, NotFoundError, ValidationError
from ...core.logging import get_logger, audit_logger
from ...core.config import settings
from ...models.audiobook import AudioBook, AudioBookChapter, AudioBookStatus
from ...repositories.audiobook import (
    AudioBookRepository,
    AudioBookChapterRepository,
    AudioBookProgressRepository
)
# Fix import error - using file_handler instead of non-existent AudioProcessor
from ...services.audio import AudioFileHandler
from ...services.cache import cache_service, CacheContext

logger = get_logger(__name__)


class ChapterOperation(Enum):
    """章节操作类型"""
    CREATE = "create"
    UPDATE = "update"
    DELETE = "delete"
    REORDER = "reorder"
    MERGE = "merge"
    SPLIT = "split"


@dataclass
class ChapterOperation:
    """章节操作"""
    type: ChapterOperation
    chapter_id: Optional[str] = None
    chapter_data: Optional[Dict[str, Any]] = None
    target_position: Optional[int] = None
    source_position: Optional[int] = None
    metadata: Dict[str, Any] = None


class ChapterManager:
    """章节管理器"""
    
    def __init__(self, session=None):
        self.audio_file_handler = AudioFileHandler()
        self.session = session
        self._audiobook_repo = None
        self._chapter_repo = None
        self._progress_repo = None
    
    @property
    def audiobook_repo(self):
        if self._audiobook_repo is None:
            self._audiobook_repo = AudioBookRepository(self.session)
        return self._audiobook_repo
    
    @property
    def chapter_repo(self):
        if self._chapter_repo is None:
            self._chapter_repo = AudioBookChapterRepository(self.session)
        return self._chapter_repo
    
    @property
    def progress_repo(self):
        if self._progress_repo is None:
            self._progress_repo = AudioBookProgressRepository(self.session)
        return self._progress_repo
    
    async def get_chapters(
        self,
        audiobook_id: str,
        user_id: Optional[str] = None,
        include_deleted: bool = False
    ) -> List[AudioBookChapter]:
        """获取有声读物章节"""
        try:
            # 检查有声读物存在和权限
            audiobook = await self._check_audiobook_access(audiobook_id, user_id)
            
            # 获取章节
            chapters = await self.chapter_repo.get_by_audiobook(audiobook_id)
            
            # 过滤已删除章节
            if not include_deleted:
                chapters = [ch for ch in chapters if ch.status != AudioBookStatus.DELETED]
            
            # 按顺序排序
            chapters.sort(key=lambda ch: ch.order)
            
            logger.info(f"Retrieved {len(chapters)} chapters for audiobook {audiobook_id}")
            return chapters
            
        except Exception as e:
            logger.error(f"Failed to get chapters: {e}")
            raise
    
    async def get_chapter(
        self,
        chapter_id: str,
        user_id: Optional[str] = None
    ) -> Optional[AudioBookChapter]:
        """获取单个章节"""
        try:
            chapter = await self.chapter_repo.get(chapter_id)
            if not chapter:
                return None
            
            # 检查权限
            await self._check_audiobook_access(chapter.audiobook_id, user_id)
            
            return chapter
            
        except Exception as e:
            logger.error(f"Failed to get chapter {chapter_id}: {e}")
            raise
    
    async def create_chapter(
        self,
        audiobook_id: str,
        chapter_data: Dict[str, Any],
        user_id: Optional[str] = None
    ) -> AudioBookChapter:
        """创建新章节"""
        try:
            # 检查有声读物存在和权限
            audiobook = await self._check_audiobook_access(audiobook_id, user_id)
            
            # 获取现有章节数量
            existing_chapters = await self.chapter_repo.get_by_audiobook(audiobook_id)
            max_order = max([ch.order for ch in existing_chapters], default=0)
            
            # 创建章节数据
            chapter_create_data = {
                "audiobook_id": audiobook_id,
                "title": chapter_data.get("title", f"第{max_order + 1}章"),
                "content": chapter_data.get("content", ""),
                "order": chapter_data.get("order", max_order + 1),
                "status": AudioBookStatus.PENDING,
                "voice_id": chapter_data.get("voice_id"),
                "voice_preset": chapter_data.get("voice_preset"),
                "voice_settings": chapter_data.get("voice_settings"),
                "duration": chapter_data.get("duration", 0.0)
            }
            
            # 创建章节
            chapter = await self.chapter_repo.create_with_attributes(**chapter_create_data)
            
            # 更新有声读物章节数
            audiobook.chapters_count = len(existing_chapters) + 1
            await self.audiobook_repo.update(audiobook, {})
            
            # 记录审计日志
            audit_logger.log_user_action(
                user_id=user_id,
                action="create_chapter",
                resource="audiobook_chapter",
                details={
                    "audiobook_id": audiobook_id,
                    "chapter_id": chapter.id,
                    "title": chapter.title
                }
            )
            
            # 使缓存失效
            cache_key = f"audiobook_chapters:{audiobook_id}"
            await cache_service.delete(cache_key)
            
            logger.info(f"Created chapter {chapter.id} for audiobook {audiobook_id}")
            return chapter
            
        except Exception as e:
            logger.error(f"Failed to create chapter: {e}")
            raise
    
    async def update_chapter(
        self,
        chapter_id: str,
        chapter_data: Dict[str, Any],
        user_id: Optional[str] = None
    ) -> Optional[AudioBookChapter]:
        """更新章节"""
        try:
            # 获取章节
            chapter = await self.chapter_repo.get(chapter_id)
            if not chapter:
                raise NotFoundError(f"Chapter {chapter_id} not found")
            
            # 检查权限
            await self._check_audiobook_access(chapter.audiobook_id, user_id)
            
            # 更新章节
            from ..schemas.audiobook import ChapterUpdate
            update_schema = ChapterUpdate(**chapter_data)
            updated_chapter = await self.chapter_repo.update(chapter, update_schema)
            
            # 如果内容发生变化，重置状态
            if "content" in chapter_data and chapter_data["content"] != chapter.content:
                updated_chapter.status = AudioBookStatus.PENDING
                updated_chapter.file_path = None
                updated_chapter.duration = 0.0
                await self.chapter_repo.update(updated_chapter, {})
            
            # 记录审计日志
            audit_logger.log_user_action(
                user_id=user_id,
                action="update_chapter",
                resource="audiobook_chapter",
                details={
                    "chapter_id": chapter_id,
                    "updated_fields": list(chapter_data.keys())
                }
            )
            
            # 使缓存失效
            cache_key = f"audiobook_chapters:{chapter.audiobook_id}"
            await cache_service.delete(cache_key)
            
            logger.info(f"Updated chapter {chapter_id}")
            return updated_chapter
            
        except Exception as e:
            logger.error(f"Failed to update chapter: {e}")
            raise
    
    async def delete_chapter(
        self,
        chapter_id: str,
        user_id: Optional[str] = None,
        permanent: bool = False
    ) -> bool:
        """删除章节"""
        try:
            # 获取章节
            chapter = await self.chapter_repo.get(chapter_id)
            if not chapter:
                return False
            
            # 检查权限
            await self._check_audiobook_access(chapter.audiobook_id, user_id)
            
            if permanent:
                # 永久删除
                success = await self.chapter_repo.remove(chapter_id)
                
                # 删除音频文件
                if chapter.file_path and os.path.exists(chapter.file_path):
                    try:
                        os.remove(chapter.file_path)
                    except Exception as e:
                        logger.error(f"Failed to delete audio file: {e}")
                
            else:
                # 软删除
                chapter.status = AudioBookStatus.DELETED
                success = await self.chapter_repo.update(chapter, {})
            
            if success:
                # 更新有声读物章节数
                existing_chapters = await self.chapter_repo.get_by_audiobook(chapter.audiobook_id)
                active_chapters = [ch for ch in existing_chapters if ch.status != AudioBookStatus.DELETED]
                
                audiobook = await self.audiobook_repo.get(chapter.audiobook_id)
                if audiobook:
                    audiobook.chapters_count = len(active_chapters)
                    await self.audiobook_repo.update(audiobook, {})
                
                # 记录审计日志
                audit_logger.log_user_action(
                    user_id=user_id,
                    action="delete_chapter",
                    resource="audiobook_chapter",
                    details={
                        "chapter_id": chapter_id,
                        "permanent": permanent
                    }
                )
                
                # 使缓存失效
                cache_key = f"audiobook_chapters:{chapter.audiobook_id}"
                await cache_service.delete(cache_key)
                
                logger.info(f"Deleted chapter {chapter_id}")
                return True
            
            return False
            
        except Exception as e:
            logger.error(f"Failed to delete chapter: {e}")
            raise
    
    async def reorder_chapters(
        self,
        audiobook_id: str,
        chapter_orders: List[Tuple[str, int]],  # (chapter_id, new_order)
        user_id: Optional[str] = None
    ) -> bool:
        """重新排序章节"""
        try:
            # 检查有声读物存在和权限
            await self._check_audiobook_access(audiobook_id, user_id)
            
            # 获取现有章节
            chapters = await self.chapter_repo.get_by_audiobook(audiobook_id)
            chapter_map = {ch.id: ch for ch in chapters}
            
            # 验证所有章节存在
            for chapter_id, _ in chapter_orders:
                if chapter_id not in chapter_map:
                    raise ValidationError(f"Chapter {chapter_id} not found")
            
            # 更新章节顺序
            for chapter_id, new_order in chapter_orders:
                chapter = chapter_map[chapter_id]
                chapter.order = new_order
                await self.chapter_repo.update(chapter, {})
            
            # 记录审计日志
            audit_logger.log_user_action(
                user_id=user_id,
                action="reorder_chapters",
                resource="audiobook_chapter",
                details={
                    "audiobook_id": audiobook_id,
                    "chapter_count": len(chapter_orders)
                }
            )
            
            # 使缓存失效
            cache_key = f"audiobook_chapters:{audiobook_id}"
            await cache_service.delete(cache_key)
            
            logger.info(f"Reordered chapters for audiobook {audiobook_id}")
            return True
            
        except Exception as e:
            logger.error(f"Failed to reorder chapters: {e}")
            raise
    
    async def merge_chapters(
        self,
        chapter_ids: List[str],
        user_id: Optional[str] = None
    ) -> Optional[AudioBookChapter]:
        """合并章节"""
        try:
            if len(chapter_ids) < 2:
                raise ValidationError("At least 2 chapters required for merging")
            
            # 获取章节
            chapters = []
            for chapter_id in chapter_ids:
                chapter = await self.chapter_repo.get(chapter_id)
                if not chapter:
                    raise NotFoundError(f"Chapter {chapter_id} not found")
                
                # 检查权限
                await self._check_audiobook_access(chapter.audiobook_id, user_id)
                chapters.append(chapter)
            
            # 检查是否属于同一个有声读物
            audiobook_id = chapters[0].audiobook_id
            if any(ch.audiobook_id != audiobook_id for ch in chapters):
                raise ValidationError("All chapters must belong to the same audiobook")
            
            # 按顺序排序
            chapters.sort(key=lambda ch: ch.order)
            
            # 合并内容
            merged_title = f"{chapters[0].title} (合并)"
            merged_content = "\n\n".join(ch.content for ch in chapters)
            merged_duration = sum(ch.duration for ch in chapters if ch.duration)
            
            # 创建新章节
            merged_chapter_data = {
                "audiobook_id": audiobook_id,
                "title": merged_title,
                "content": merged_content,
                "order": chapters[0].order,
                "status": AudioBookStatus.PENDING,
                "duration": merged_duration
            }
            
            merged_chapter = await self.chapter_repo.create_with_attributes(**merged_chapter_data)
            
            # 删除原章节
            for chapter in chapters:
                await self.delete_chapter(chapter.id, user_id, permanent=True)
            
            # 重新排序剩余章节
            await self._renumber_chapters(audiobook_id)
            
            # 记录审计日志
            audit_logger.log_user_action(
                user_id=user_id,
                action="merge_chapters",
                resource="audiobook_chapter",
                details={
                    "audiobook_id": audiobook_id,
                    "source_chapters": chapter_ids,
                    "merged_chapter": merged_chapter.id
                }
            )
            
            # 使缓存失效
            cache_key = f"audiobook_chapters:{audiobook_id}"
            await cache_service.delete(cache_key)
            
            logger.info(f"Merged {len(chapters)} chapters into {merged_chapter.id}")
            return merged_chapter
            
        except Exception as e:
            logger.error(f"Failed to merge chapters: {e}")
            raise
    
    async def split_chapter(
        self,
        chapter_id: str,
        split_points: List[int],  # 字符位置
        user_id: Optional[str] = None
    ) -> List[AudioBookChapter]:
        """拆分章节"""
        try:
            # 获取章节
            chapter = await self.chapter_repo.get(chapter_id)
            if not chapter:
                raise NotFoundError(f"Chapter {chapter_id} not found")
            
            # 检查权限
            await self._check_audiobook_access(chapter.audiobook_id, user_id)
            
            if not split_points:
                raise ValidationError("At least one split point required")
            
            # 验证分割点
            content = chapter.content
            for point in split_points:
                if point <= 0 or point >= len(content):
                    raise ValidationError(f"Invalid split point: {point}")
            
            # 排序分割点
            split_points = sorted(set(split_points))
            
            # 分割内容
            parts = []
            last_point = 0
            
            for point in split_points:
                parts.append(content[last_point:point])
                last_point = point
            parts.append(content[last_point:])
            
            # 创建新章节
            new_chapters = []
            base_order = chapter.order
            
            for i, part in enumerate(parts):
                chapter_data = {
                    "audiobook_id": chapter.audiobook_id,
                    "title": f"{chapter.title} - 第{i+1}部分",
                    "content": part.strip(),
                    "order": base_order + i,
                    "status": AudioBookStatus.PENDING,
                    "voice_id": chapter.voice_id,
                    "voice_preset": chapter.voice_preset,
                    "voice_settings": chapter.voice_settings
                }
                
                new_chapter = await self.chapter_repo.create_with_attributes(**chapter_data)
                new_chapters.append(new_chapter)
            
            # 删除原章节
            await self.delete_chapter(chapter_id, user_id, permanent=True)
            
            # 重新排序剩余章节
            await self._renumber_chapters(chapter.audiobook_id)
            
            # 记录审计日志
            audit_logger.log_user_action(
                user_id=user_id,
                action="split_chapter",
                resource="audiobook_chapter",
                details={
                    "audiobook_id": chapter.audiobook_id,
                    "source_chapter": chapter_id,
                    "split_points": split_points,
                    "new_chapters": [ch.id for ch in new_chapters]
                }
            )
            
            # 使缓存失效
            cache_key = f"audiobook_chapters:{chapter.audiobook_id}"
            await cache_service.delete(cache_key)
            
            logger.info(f"Split chapter {chapter_id} into {len(new_chapters)} parts")
            return new_chapters
            
        except Exception as e:
            logger.error(f"Failed to split chapter: {e}")
            raise
    
    async def get_chapter_statistics(
        self,
        chapter_id: str,
        user_id: Optional[str] = None
    ) -> Dict[str, Any]:
        """获取章节统计信息"""
        try:
            # 获取章节
            chapter = await self.chapter_repo.get(chapter_id)
            if not chapter:
                raise NotFoundError(f"Chapter {chapter_id} not found")
            
            # 检查权限
            await self._check_audiobook_access(chapter.audiobook_id, user_id)
            
            # 计算统计信息
            content = chapter.content
            word_count = len(content.split()) if content else 0
            char_count = len(content) if content else 0
            estimated_reading_time = char_count / 300 if content else 0  # 300字/分钟
            
            # 音频文件信息
            file_info = {}
            if chapter.file_path and os.path.exists(chapter.file_path):
                try:
                    # Note: AudioFileHandler may not have get_audio_info method
                    # We'll just get file size for now
                    file_info = {
                        "file_size": os.path.getsize(chapter.file_path),
                        "duration": chapter.duration
                    }
                except Exception as e:
                    logger.error(f"Failed to get audio info: {e}")
            
            stats = {
                "chapter_id": chapter_id,
                "word_count": word_count,
                "char_count": char_count,
                "estimated_reading_time": estimated_reading_time,
                "audio_duration": chapter.duration,
                "file_info": file_info,
                "status": chapter.status.value,
                "created_at": chapter.created_at.isoformat() if chapter.created_at else None,
                "updated_at": chapter.updated_at.isoformat() if chapter.updated_at else None
            }
            
            return stats
            
        except Exception as e:
            logger.error(f"Failed to get chapter statistics: {e}")
            raise
    
    async def batch_process_chapters(
        self,
        chapter_ids: List[str],
        operation: ChapterOperation,
        operation_data: Dict[str, Any],
        user_id: Optional[str] = None
    ) -> List[Dict[str, Any]]:
        """批量处理章节"""
        try:
            results = []
            
            for chapter_id in chapter_ids:
                try:
                    if operation == ChapterOperation.DELETE:
                        success = await self.delete_chapter(chapter_id, user_id)
                        results.append({"chapter_id": chapter_id, "success": success})
                    
                    elif operation == ChapterOperation.UPDATE:
                        success = await self.update_chapter(chapter_id, operation_data, user_id)
                        results.append({"chapter_id": chapter_id, "success": bool(success)})
                    
                    else:
                        results.append({"chapter_id": chapter_id, "success": False, "error": "Unsupported operation"})
                        
                except Exception as e:
                    results.append({"chapter_id": chapter_id, "success": False, "error": str(e)})
            
            # 记录审计日志
            audit_logger.log_user_action(
                user_id=user_id,
                action="batch_process_chapters",
                resource="audiobook_chapter",
                details={
                    "operation": operation.value,
                    "chapter_count": len(chapter_ids),
                    "results": [r for r in results if r.get("success")]
                }
            )
            
            logger.info(f"Batch processed {len(chapter_ids)} chapters with operation {operation.value}")
            return results
            
        except Exception as e:
            logger.error(f"Failed to batch process chapters: {e}")
            raise
    
    async def _check_audiobook_access(
        self,
        audiobook_id: str,
        user_id: Optional[str] = None
    ) -> AudioBook:
        """检查有声读物访问权限"""
        audiobook = await self.audiobook_repo.get(audiobook_id)
        if not audiobook:
            raise NotFoundError(f"Audiobook {audiobook_id} not found")
        
        # 检查权限
        if user_id and audiobook.user_id != user_id and audiobook.status != AudioBookStatus.COMPLETED:
            raise ValidationError("Access denied")
        
        return audiobook
    
    async def _renumber_chapters(self, audiobook_id: str):
        """重新编号章节"""
        chapters = await self.chapter_repo.get_by_audiobook(audiobook_id)
        active_chapters = [ch for ch in chapters if ch.status != AudioBookStatus.DELETED]
        
        # 按当前顺序排序并重新编号
        active_chapters.sort(key=lambda ch: ch.order)
        
        for i, chapter in enumerate(active_chapters):
            chapter.order = i + 1
            await self.chapter_repo.update(chapter, {})
    
    async def export_chapters(
        self,
        audiobook_id: str,
        format: str = "json",
        user_id: Optional[str] = None
    ) -> Dict[str, Any]:
        """导出章节数据"""
        try:
            # 检查权限
            await self._check_audiobook_access(audiobook_id, user_id)
            
            # 获取章节
            chapters = await self.get_chapters(audiobook_id, user_id)
            
            if format == "json":
                return {
                    "audiobook_id": audiobook_id,
                    "export_time": datetime.utcnow().isoformat(),
                    "chapters": [chapter.to_dict() for chapter in chapters]
                }
            
            elif format == "txt":
                content = ""
                for chapter in chapters:
                    content += f"# {chapter.title}\n\n"
                    content += chapter.content + "\n\n"
                
                return {
                    "format": "txt",
                    "content": content,
                    "audiobook_id": audiobook_id,
                    "export_time": datetime.utcnow().isoformat()
                }
            
            else:
                raise ValidationError(f"Unsupported export format: {format}")
                
        except Exception as e:
            logger.error(f"Failed to export chapters: {e}")
            raise


# 全局章节管理器实例
chapter_manager = ChapterManager()
